package com.example.base.crash

import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import java.io.*
import java.text.SimpleDateFormat
import java.util.*

/**
 */
object CrashLog {
    const val TAG = "CrashLog"
    fun saveCrashLog(context: Context, throwable: Throwable) {
        val map = collectDeviceInfo(context)
        saveCrashInfo2File(context, throwable, map)
    }

    private fun collectDeviceInfo(ctx: Context): Map<String, String> {
        val infos: MutableMap<String, String> = TreeMap()
        try {
            infos["systemVersion"] = Build.VERSION.RELEASE
            val pm = ctx.packageManager
            val pi = pm.getPackageInfo(ctx.packageName, PackageManager.GET_ACTIVITIES)
            if (pi != null) {
                val versionName = if (pi.versionName == null) "null" else pi.versionName
                val versionCode = pi.versionCode.toString() + ""
                infos["versionName"] = versionName
                infos["versionCode"] = versionCode
            }
        } catch (e: PackageManager.NameNotFoundException) {
        }
        val fields = Build::class.java.declaredFields
        for (field in fields) {
            try {
                field.isAccessible = true
                infos[field.name] = field[null].toString()
            } catch (e: Exception) {
            }
        }
        return infos
    }

    private fun saveCrashInfo2File(context: Context, ex: Throwable, infos: Map<String, String>) {
        val sb = StringBuilder()
        for ((key, value) in infos) {
            sb.append(key).append("=").append(value).append("\n")
        }
        val writer: Writer = StringWriter()
        val printWriter = PrintWriter(writer)
        ex.printStackTrace(printWriter)
        var cause = ex.cause
        while (cause != null) {
            cause.printStackTrace(printWriter)
            cause = cause.cause
        }
        printWriter.close()
        val result = writer.toString()
        sb.append(result)
        try {
            val timestamp = System.currentTimeMillis()
            val time = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Date())
            val fileName = "crash-$time-$timestamp.log"
            val cachePath = crashLogDir(context)
            val dir = File(cachePath)
            dir.mkdirs()
            val fos = FileOutputStream(cachePath + fileName)
            fos.write(sb.toString().toByteArray())
            fos.close()
        } catch (e: Exception) {
        }
    }

    fun crashLogDir(context: Context?): String {
        return context!!.cacheDir.path + File.separator + "crash" + File.separator
    }
}